{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Styling of Jupyter widgets\n", "\n", "This notebook presents how to style Jupyter interactive widgets to build rich and *reactive* widget-based applications." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can jump directly to these sections:\n", "\n", "+ [Predefined styles](#Predefined-styles)\n", "+ [The style attribute](#The-style-attribute)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Predefined styles\n", "\n", "If you wish the styling of widgets to make use of colors and styles defined by the environment (to be consistent with e.g. a notebook theme), many widgets enable choosing in a list of pre-defined styles.\n", "\n", "For example, the `Button` widget has a `button_style` attribute that may take 5 different values:\n", "\n", " - `'primary'`\n", " - `'success'`\n", " - `'info'`\n", " - `'warning'`\n", " - `'danger'`\n", "\n", "besides the default empty string ''." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from ipywidgets import Button\n", "\n", "Button(description='Danger Button', button_style='danger')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The `style` attribute\n", "\n", "While the `layout` attribute only exposes layout-related CSS properties for the top-level DOM element of widgets, the \n", "`style` attribute is used to expose non-layout related styling attributes of widgets.\n", "\n", "However, the properties of the `style` attribute are specific to each widget type." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "b1 = Button(description='Custom color')\n", "b1.style.button_color = 'lightgreen'\n", "b1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can get a list of the style attributes for a widget with the `keys` property." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "b1.style.keys" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Just like the `layout` attribute, widget styles can be assigned to other widgets." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "b2 = Button()\n", "b2.style = b1.style\n", "b2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Widget styling attributes are specific to each widget type." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from ipywidgets import IntSlider\n", "\n", "s1 = IntSlider(description='Blue handle')\n", "s1.style.handle_color = 'lightblue'\n", "s1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Styles can be given when a widget is constructed, either as a specific Style instance or as a dictionary." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "b3 = Button(description='Styled button', style=dict(\n", " font_style='italic',\n", " font_weight='bold',\n", " font_variant=\"small-caps\",\n", " text_color='red',\n", " text_decoration='underline'\n", "))\n", "b3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Current supported attributes\n", "\n", "Currently, the styling attributes that are supported vary from widget to widget. Here is the list of which different `Style` widgets are used by the various other widgets:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from collections import defaultdict\n", "from IPython.display import HTML\n", "import ipywidgets\n", "from pprint import pprint" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "reverse_lut = defaultdict(set)\n", "styles = set()\n", "for export_name in dir(ipywidgets.widgets):\n", " export = getattr(ipywidgets.widgets, export_name)\n", " try:\n", " if issubclass(export, ipywidgets.Widget) and 'style' in export.class_trait_names():\n", " reverse_lut[export.style.klass.__name__].add(export.__name__)\n", " styles.add(export.style.klass)\n", " except TypeError:\n", " pass\n", "\n", "html = '\"\n", "HTML(html)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And here are the different attributes that the different `Style` widgets support:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "attributes = defaultdict(set)\n", "base_traits = set(ipywidgets.Style.class_trait_names())\n", "\n", "for s in styles:\n", " for t in s.class_trait_names():\n", " if not t.startswith(\"_\") and t not in base_traits:\n", " attributes[s.__name__].add(t)\n", "all_attributes = set().union(*attributes.values())\n", "\n", "html = '\\n'\n", "html = f\"{html}{ ''.join(f'' for s in attributes.keys()) }\"\n", "for a in all_attributes:\n", " html = f\"\"\"{html}{ ''.join(f'' for attribs in attributes.values()) }\"\"\"\n", "html += \"
Attribute{s}
{a}{\"✓\" if a in attribs else \"\"}
\"\n", "HTML(html)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 4 }